﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Diagnostics;

namespace AbyssCombatLogger
{
    public class EventHandlers
    {
        ProgressBar pbForUpdating;
        TextBox tbForUpdating;
        Dictionary<string, Player> playersList = new Dictionary<string, Player>();
        Dictionary<string, Enemy> enemiesList = new Dictionary<string, Enemy>();
        //frmMeter Meter;
        public Hashtable htGroupThreatFromLog = new Hashtable(); //moved from frmMeter

        public EventHandlers(ref ProgressBar pbForUpdating, ref TextBox tbForUpdating,
            ref Dictionary<string, Player> playersList, ref Dictionary<string, Enemy> enemiesList)//SHOULD ADD: , ref SortedList<string, Player> enemiesList)
        {
            this.pbForUpdating = pbForUpdating;
            this.tbForUpdating = tbForUpdating;
            this.playersList = playersList;
            this.enemiesList = enemiesList;
            //this.Meter = meter;
        }

        public Hashtable htTotalDamagesByPlayer = new Hashtable();
        public Hashtable htTotalHealsByPlayer = new Hashtable();


        private void UpdateHateFromDamage(ref Hashtable targetHateTables, ParsedLogEvent enemy_dmg)
        {


            string tar = GetNameNotPet(enemy_dmg.Target);
            //check if target is a pet, dont generate aggro since pets seem to have no aggro tables on mobs

            string player = GetNameNotPet(enemy_dmg.Actor);
            
            if (enemy_dmg.Actor.Contains("Ashie"))// && tar == "Balbet-Zhun")
            {
                Debug.Assert(true);
            }
            if (tar == "You") //&& clientPlayerName == player)
            {
                //client damaged themeselves
                //tar = clientPlayerName;
                return;
            }
            else if (tar == player)
            {
                return;
            }


            //else if (player.Contains(" ") || (enemiesList !=null && enemiesList.ContainsKey(player)))
            //{

            //}
            //else if (playersList==null || playersList.Count == 0)
            //{

            //}
            ////else if (playersList != null && playersList.ContainsKey(tar)) // a player is the target therefore the actor is an enemy, and players dont have threat tables of their own, only on enemey targets
            ////{
            ////    return;
            ////}
            else if (enemiesList != null && enemiesList.ContainsKey(player))
            {
                return;
            }
            
            //attribute damage from player's pet to the player (except for enrage ability i think)
            string actorTakingBlame = player;
            //int ioQuote = player.IndexOf("'");

            //if (ioQuote != -1) //player is pet
            //{
            //    actorTakingBlame = player.Substring(0, ioQuote);
            //}
            //else
            //    actorTakingBlame = player;


            //float defKd = 1.0f;
            //float kD = 1.0f;
            //if (playersList != null && playersList.ContainsKey(actorTakingBlame))
            //{
            //    Player p = playersList[actorTakingBlame];
            //    kD = p.ThreatRating;
            //}
            //else
            //    kD = defKd;
            float kD = GetPlayerHateConstant(actorTakingBlame);

            if (enemy_dmg.Actor.Contains("Ashie"))// && tar == "Balbet-Zhun")
            {
                Debug.Assert(true);
            }

            float t = kD * enemy_dmg.AmountInt;
            if (tar != actorTakingBlame) //cant do threat on self doesnt make any sense to do so
                AddThreatOfPlayerOnTarget(ref targetHateTables, tar, actorTakingBlame, t);


        } //end of procedure

        private static void AddThreatOfPlayerOnTarget(ref Hashtable targetHateTables, string tar, string player, float t)
        {
            if (t != 0)
            {
                float targetsHate = GetThreatOfPlayerOnEnemy(ref targetHateTables, tar, player);

                Hashtable hashOfPlayers_Hate = null;

                if (targetHateTables == null)
                {
                    targetHateTables = new Hashtable();
                }


                if (tar != null && !targetHateTables.ContainsKey(tar))
                {
                    //create a new hate table and place it in the hashtable of targets hatetables
                    hashOfPlayers_Hate = new Hashtable();
                    hashOfPlayers_Hate.Add(player, t);
                    targetHateTables.Add(tar, hashOfPlayers_Hate);
                }
                else if (tar
                    != null)
                {
                    hashOfPlayers_Hate = (Hashtable)targetHateTables[tar];

                    if (!hashOfPlayers_Hate.ContainsKey(player))
                    {
                        hashOfPlayers_Hate.Add(player, t);
                    }
                    else
                    {
                        hashOfPlayers_Hate[player] = targetsHate + t;
                    }
                } //end if then else
            }
        }

        private static float GetThreatOfPlayerOnEnemy(ref Hashtable enemyHateTables, string enemy, string player)
        {
            if (enemyHateTables == null)
                return 0;
            else if (enemyHateTables.Count != 0)
            {

                //calculate threat from damage
                float targetsHate = 0;
                Hashtable enemiesHateTable = null;

                if (enemy == null)
                    return 0;
                enemiesHateTable = (Hashtable)enemyHateTables[enemy];
                if (enemiesHateTable != null && enemiesHateTable.Contains(player))
                    targetsHate = (float)((Hashtable)enemiesHateTable)[player];
                else
                    targetsHate = 0;
                return targetsHate;
            }
            else return 0;
        }

            private void UpdateHateFromHeal(ref Hashtable htAllTargetThreatTables, ParsedLogEvent healed_amount)
            {

                string tar = GetNameNotPet(healed_amount.Target);
                //check if target is a pet, dont generate aggro since pets seem to have no aggro tables on mobs

                string player = GetNameNotPet(healed_amount.Actor);
                ////now if player is a pet make actor the player not the pet                   
                //int ioQuoteInActor = healed_amount.Actor.IndexOf("'");
                //if (ioQuoteInActor != -1) 
                //{
                //    player = healed_amount.Actor.Substring(0, ioQuoteInActor);
                //}
                //else
                //    player = healed_amount.Actor;

                float healAmount = healed_amount.AmountInt;

                if (enemiesList.ContainsKey(player)) //doesnt make sense to compute threat table of an enemy on real player target; hate tables for actor player and target enemy only
                    return;
                if (enemiesList.ContainsKey(tar))                    
                    return;

                //calculate threat from heal
                //incremental threat from healing, t =  k*h*(player_healed's_threat_on_target/TotalThreatOnTarget) + E

                if (healAmount != 0)
                {
                    Hashtable targetsThreatTable = null;

                    //make sure there are threat tables and make sure that the player in question has a threat table too
                    if (htAllTargetThreatTables == null)
                    {
                        htAllTargetThreatTables = new Hashtable();
                        //htAllTargetThreatTables.Add(tar, targetsThreatTable);
                    }
                    if (htAllTargetThreatTables.Count != 0 && tar != null && htAllTargetThreatTables.Contains(tar))
                        targetsThreatTable = (Hashtable)htAllTargetThreatTables[player];
                    else
                    {
                        targetsThreatTable = new Hashtable(); //create new threat table
                        if (tar != null)
                            htAllTargetThreatTables.Add(tar, targetsThreatTable);
                    }

                    //if (targetsThreatTable != null && targetsThreatTable.Count > 0)
                    //{
                        //List<ParsedLogEvent> threatsToAdd = null;
                        //if (targetsThreatTable.Count > 0)
                        //{
                        //    threatsToAdd = new List<ParsedLogEvent>();
                        //}
                        float kh = GetPlayerHateConstant(player);

                        foreach (string enemy in htAllTargetThreatTables.Keys)
                        {

                            Hashtable enemiesHateTable = (Hashtable)htAllTargetThreatTables[enemy];
                            float totalHateInEnemyHateTable = GetTotalThreatOnTarget(enemiesHateTable);

                            if (totalHateInEnemyHateTable != 0 && enemiesHateTable.ContainsKey(tar))
                            {
                                float totalEnemyHateOnTarget = GetThreatOfPlayerOnEnemy(ref htAllTargetThreatTables, enemy, tar);
                                if (totalEnemyHateOnTarget != 0)
                                {
                                    float incrementalThreat = kh * healAmount * totalEnemyHateOnTarget / totalHateInEnemyHateTable;
                                    AddThreatOfPlayerOnTarget(ref htAllTargetThreatTables, enemy, player, incrementalThreat);
                                }
                                //else incremental threat 0 does not need to be added since 0+x = x

                            }

                        }
                        //if (threatsToAdd != null)
                        //{
                        //    foreach (ParsedLogEvent evt in threatsToAdd)
                        //    {
                        //        AddThreatOfPlayerOnTarget(ref htAllTargetThreatTables, evt.Target, evt.Actor, evt.AmountInt);
                        //    }
                        //}
                    }
                    else
                    {

                        
                    }
                //}
            }

            private static string GetNameNotPet(string tar)
            {
                int ioQuoteInTarget = tar.IndexOf("'");

                if (ioQuoteInTarget != -1) //player is pet
                {
                    tar = tar.Substring(0, ioQuoteInTarget); ; //should return
                }
                else
                {
                    int ioYourInTarget = tar.IndexOf("Your");
                    if (ioYourInTarget != -1)
                        tar = "You";
                }
                return tar;
            }

            private float GetPlayerHateConstant(string player)
            {
                float kh;
                float defKh = 1.0f;
                if (playersList != null && playersList.ContainsKey(player))
                {
                    Player p = playersList[player];
                    kh = p.ThreatRating;
                }
                else
                    kh = defKh;
                return kh;
            }
            
        //private void AddHateOnAllPossibleEnemies(string tar, string player, float h, Hashtable targetsThreatTable)
        //    {
        //        ////if (targetsThreatTable == null)
        //        ////    return htAllTargetThreatTables;
            
        //        foreach (string playerHated in targetsThreatTable.Keys)
        //        {
                    

        //            float targetsOldHate;

        //            //if (targetsThreatTable.Contains(playerHated))
        //            if (targetsThreatTable.ContainsKey(tar))
        //                targetsOldHate = (float)(targetsThreatTable[tar]);
        //            else
        //                targetsOldHate = 0;

        //            float totalTargetThreat
           
        //                //totalTargetsHate += (float)targetsHateOnPlayers[playerHated];

        //            ///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct
        //            float t;
        //            float defKh = 1.0f;
        //            float kh = 1.0f;
        //            if (playersList != null && playersList.ContainsKey(player))
        //            {
        //                Player p = playersList[player];
        //                kh = p.ThreatRating;
        //            }
        //            else
        //                kh = defKh;
        //            t = kh * h * (targetsOldHate / totalTargetThreat);

        //            if (t != 0)///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct
        //                AddThreatOfPlayerOnTarget(ref htAllTargetThreatTables, tar, player, t);
        //            ///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct

        //        }
        //    }

            //private Hashtable AddHateOnAllPossibleEnemies(ref Hashtable htAllTargetThreatTables, string tar, string player, float h, Hashtable targetsThreatTable)
            //{
            //    ////if (targetsThreatTable == null)
            //    ////    return htAllTargetThreatTables;

            //    foreach (string playerHated in targetsThreatTable.Keys)
            //    {

            //        float targetsOldHate;

            //        //if (targetsThreatTable.Contains(playerHated))
            //        if (targetsThreatTable.ContainsKey(tar))
            //            targetsOldHate = (float)(targetsThreatTable[tar]);
            //        else
            //            targetsOldHate = 0;

            //        float totalTargetThreat
            //        //totalTargetsHate += (float)targetsHateOnPlayers[playerHated];

            //        ///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct
            //        float t;
            //        float defKh = 1.0f;
            //        float kh = 1.0f;
            //        if (playersList != null && playersList.ContainsKey(player))
            //        {
            //            Player p = playersList[player];
            //            kh = p.ThreatRating;
            //        }
            //        else
            //            kh = defKh;
            //        t = kh * h * (targetsOldHate / totalTargetThreat);

            //        if (t != 0)///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct
            //            AddThreatOfPlayerOnTarget(ref htAllTargetThreatTables, tar, player, t);
            //        ///THE INCREMENTAL HATE EQUATION LOOKS SIMPLE, and its proportionalities look about correct

            //    }
            //    return htAllTargetThreatTables;
            //}

            private static float GetTotalThreatOnTarget(Hashtable targetsHateTable)
            {
                if (targetsHateTable == null || targetsHateTable.Count == 0)
                    return 0;
                else
                {
                    float totalThreatOnTarget = 0;
                    foreach (string player in targetsHateTable.Keys)
                    {
                        totalThreatOnTarget += Convert.ToSingle(targetsHateTable[player]);
                    }
                    return totalThreatOnTarget;
                }
            }


            public long GetTotalDamages()
            {
                if (htTotalDamagesByPlayer == null || htTotalDamagesByPlayer.Count == 0)
                    return 0;
                else
                {
                    long totalDamage = 0;
                    foreach (string player in htTotalDamagesByPlayer.Keys)
                    {
                        totalDamage += Convert.ToInt64(htTotalDamagesByPlayer[player]);
                    }
                    return totalDamage;
                }
            }




        const int spaceBufferForName = 20;
        public static string GetBar(string player, float amount, float total)
        {
            int spacesInLong = 12;//long.MaxValue.ToString().Length;
            string sAmount = ((long)amount).ToString();
            string threatBuffer = BufferLeft(" ", sAmount, spacesInLong);
            player = player.Substring(0, player.Length > spaceBufferForName ? spaceBufferForName : player.Length); //make sure is not greater than the maximum length given
            string nameBuffer = BufferRight(" ", player, spaceBufferForName);

            float frac = amount / total;
            int charsMaxInBar = 20;
            int charsInBar = (int)(frac * charsMaxInBar);
            int charsRemaining = charsMaxInBar - charsInBar;
            string bar = Repeat("*", charsInBar);
            bar = bar + Repeat(" ", charsRemaining);
            string finalStr = nameBuffer + threatBuffer + " " + bar;
            return finalStr;
        }

        public static string BufferRight(string padStr, string toBuffer, int length)
        {
            if (toBuffer.Length < length)
            {
                StringBuilder sb = new StringBuilder(toBuffer);
                for (int i = 0; i < length - toBuffer.Length; i++)
                {
                    sb.Append(padStr);
                }
                return sb.ToString();
            }
            else
                return toBuffer;
        }
        public static string BufferLeft(string padStr, string toBuffer, int length)
        {
            if (toBuffer.Length < length)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < length - toBuffer.Length; i++)
                {
                    sb.Append(padStr);
                }
                sb.Append(toBuffer);
                return sb.ToString();
            }
            else
                return toBuffer;
        }
        public static string Repeat(string toRepeat, int count)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < count; i++)
                sb.Append(toRepeat);
            return sb.ToString();
        }
        //public class DamageEvent
        //{
        //    public int amount;
        //    //public string actor = null;
        //    public string target = "";
        //    public string spellName = "";
        //    DamageEvent(string target, int amount, string spellsName)
        //    {
        //        this.target = target;
        //        this.amount = amount;
        //        this.spellName = spellsName;
        //    }
        //}

        public bool Coppice_GroupDamagingStarted = false;
        public bool Coppice_InCoppice = false;
        public bool Coppice_TreasureDamaged = false;
        public bool Coppice_BossDown = false;

        public ParsedLogEvent LastDamageEvent = null;

        public delegate void HandleDamageDelegate(ParsedLogEvent logDamageEvent);
        public event HandleDamageDelegate Damage;

        public void HandleDamage(ParsedLogEvent logDamageEvent)
        {
            string targetPet = GetNameNotPet(logDamageEvent.Target);
            if (targetPet == logDamageEvent.Target)
            {
                //may be damage by a player on another person pet (ie. Travino's Protective Spirit)
                DoHandleDamage(logDamageEvent);
                if (Damage != null)
                    Damage(logDamageEvent);
            }
            else
            {
                Debug.Assert(true);//
            }
        }

        public Dictionary<string, Dictionary<string, long>> damagesByPlayerOnTargets = new Dictionary<string, Dictionary<string, long>>();

        private void DoHandleDamage(ParsedLogEvent logDamageEvent)
        {
            // check for Outer Membrane

            //few cases enemy -> enemy (least common), 
            ///player -> player (pvp scenario/ mind controlled), 
            ///player -> enemy && 
            ///enemy -> player
            //if its something attacking something something could be player or enemy
            //if name contains space its a definate enemy

            bool actorIsEnemy = CheckForEnemy(logDamageEvent.Actor, false);//logDamageEvent.ActorIsPet);
            bool targetIsEnemy = CheckForEnemy(logDamageEvent.Target, false);
            //if its an enemy attacking someone its efinatlly a known player
            if (actorIsEnemy)
            {
                //enemy is damaging a player not another enemy, unless its some wierd scenario of a wolf attacking a rabbit
                if (!logDamageEvent.Target.Contains(" ") && !logDamageEvent.Target.Contains("-") && !logDamageEvent.Target.Contains("'")
                  && enemiesList.ContainsKey(logDamageEvent.Target))
                    AddKnownPlayer(logDamageEvent.Target);
            }

            ///
            ///
            UpdateHateFromDamage(ref htGroupThreatFromLog, logDamageEvent);

            ///Add place for accounting of damage against a target (by a player).
            //htDamageDoneOnEnemies 
            string tar = GetNameNotPet(logDamageEvent.Target);
            string player = GetNameNotPet(logDamageEvent.Actor);

            if (tar == "You")
            {
                //client damaged themeselves
                //tar = clientPlayerName;
                return;
            }
            else if (tar == player) //client damaged themeselves
            {
                return;
            }
            else if (enemiesList != null && enemiesList.ContainsKey(player))
            {
                return;  //there shall be only player damages..no enemies..in the damage tallies
            }
        
            //save the new information to a hashtable
            if (damagesByPlayerOnTargets.ContainsKey(player))
            {
                Dictionary<string, long> damageToTargets = damagesByPlayerOnTargets[player];

                if (damageToTargets.ContainsKey(tar))
                {
                    long d = damageToTargets[tar];
                    //now incrememnt this with the new damage value
                    d += logDamageEvent.Amount;
                    //now save the new damage amount back to its unique storage
                    damageToTargets[tar] = d;
                }
                else
                {
                    damageToTargets.Add(tar, logDamageEvent.Amount);
                }
            }
            else
            {
                Dictionary<string, long> damageToTargets = new Dictionary<string,long>();
                damageToTargets.Add(tar, logDamageEvent.Amount);
                damagesByPlayerOnTargets.Add(player, damageToTargets);
            }

        
        }

        private bool CheckForEnemy(string name, bool ActorIsKnownPet)
        {
            if (name != null && (name.Contains(" ") &&
                !ActorIsKnownPet) || name.Contains("-"))
            {
                //known enemy
                if (!enemiesList.ContainsKey(name))
                {
                    enemiesList.Add(name, new Enemy(name));
                }
                return true;
            }
            else return false;
        }

        /*
        private void HandleCoppice(ParsedLogEvent logDamageEvent)
        {
            if (IsLogging && logDamageEvent.Target == "Outer Membrane")
            {
                Coppice_InCoppice = true;
                Meter.InfoLogIt("Coppice run started on epic mode.", null, "Epic coppice started.");
            }
            else if (IsLogging && logDamageEvent.Target == "Inner Membrane")
            {
                Meter.InfoLogIt("Coppice run started on regular difficulty. To start it on epic every member must leave the group and form a new group.", null, "Coppice run started on regular difficulty.");
            }
            if (IsLogging && Coppice_InCoppice)
            {
                if (logDamageEvent.Actor == "Stranger" && logDamageEvent.Spell == "Bloodswarm")
                {
                    //Stranger's Bloodswarm remedy
                    logDamageEvent.Actor = "Balbet-Zhun"; //make modifications for the parsing mistake
                    Coppice_GroupDamagingStarted = true;
                    Coppice_TreasureDamaged = false;
                }
                if (logDamageEvent.Target == "Trial Treasures")
                    Coppice_TreasureDamaged = true;
            }
        }
        */

         private void AddEventAmountTo(Hashtable theEventHash, ParsedLogEvent logEvent)
        {
            if (logEvent.AmountInt != 0)
            {
                string player = logEvent.Actor;


                if (theEventHash.Count != 0 && theEventHash.ContainsKey(player))
                {
                    theEventHash[player] = Convert.ToInt64(theEventHash[player]) + logEvent.AmountInt;
                }
                else //if (!player.Contains(" ")) //definate enemy
                {
                    if (player != "You" && theEventHash == this.htTotalHealsByPlayer)
                    {
                        Debug.Assert(true);
                    }
                    theEventHash.Add(player, (long)logEvent.AmountInt);
                }
            }

        }

        public delegate void HandleHealDelegate(ParsedLogEvent logHealEvent);
        public event HandleHealDelegate Heal;

        public void HandleHeal(ParsedLogEvent logHealEvent)
        {
            DoHandleHeal(logHealEvent);
            if (Heal!=null)
                Heal(logHealEvent);
        }

        private void DoHandleHeal(ParsedLogEvent logHealEvent)
        {
            //if (logHealEvent.Spell == "Trial of the Godslayer")
            //{
            //    //coppice mob runs out
            //    Meter.InfoLogIt("Runner should do a quick ranged damaging attack and run, now, and begin to circle. Trial of the Godslayer has started. The boss has 1.4 million health. Do not get hit in melee as it may reset the boss' aggro table.", null, "The runner should quickly damage boss and begin circling.");
            //}
            //else
            {
                bool actorIsEnemy = CheckForEnemy(logHealEvent.Actor, false);


                if (!logHealEvent.ActorIsPet && actorIsEnemy == false)
                {
                    //also add the healing since no healing shows up for mobs
                    AddKnownPlayer(logHealEvent.Actor);
                }

                //if its a player healing someone that someone is probably a player unless he's mind controlled...
                if (playersList != null && playersList.ContainsKey(logHealEvent.Actor))
                {
                    //assume no mind control, known players heal only one thing, known players
                    AddKnownPlayer(logHealEvent.Target);
                }

                //if target is enemy then a heal from an actor would be a heal would probably be from another enemy
                bool targetIsEnemy = CheckForEnemy(logHealEvent.Actor, false);

                //do threat now
                UpdateHateFromHeal(ref htGroupThreatFromLog, logHealEvent);

                if (logHealEvent.Actor != "You")
                    Debug.Assert(true);

                if (!actorIsEnemy)
                    AddEventAmountTo(htTotalHealsByPlayer, logHealEvent);
            }
        }

        private void AddKnownPlayer(string p)
        {
            if (p != null && p != "")
            {
                if (!playersList.ContainsKey(p))
                    playersList.Add(p, new Player(p));
            }
            else
            {
                //throw new Exception("Player name cannot be the empty string.");
            }
        }

        public delegate void HandleCastDelegate(DateTime timeStamp, string player, string spellName);
        public event HandleCastDelegate Cast;

        public void HandleCast(DateTime timeStamp, string player, string spellname)
        {
            DoHandleCast(player, spellname);
            if (Cast!=null)
                Cast(timeStamp, player, spellname);
        }

        private static void DoHandleCast(string player, string spellname)
        {
            //SHOULD HAVE CASTS / SECOND FOR ALL RAID MEMBERS
            //Shield of the Risen
            //Defensive Stance
            //string errormesg = "not handled: " + player + " casts " + spellname;
            //Debug.WriteLine(errormesg);
            //tbForUpdating.Text = errormesg;
        }

        public long GetMaxDamagePlayer(out string PlayerWithMax)
        {
            PlayerWithMax = null;       
            long maxTotalByPlayer = 0;
            foreach (string player in htTotalDamagesByPlayer.Keys)
            {
                if (player == null || player == "")// && !player.Contains("'"))
                { }
                else
                {
                    long totalByPlayer = Convert.ToInt64(htTotalDamagesByPlayer[player]);
                    if (totalByPlayer > maxTotalByPlayer)
                    {
                        PlayerWithMax = player;
                        maxTotalByPlayer = totalByPlayer;
                    }
                 }
            }
            return maxTotalByPlayer;
        }
        public List<Stat> GetPlayersSortedByDamage()
        {
            List<Stat> sortedList;
            StatComparer comparer = new StatComparer(StatType.Damage);


            if (this.htTotalDamagesByPlayer.Count == 0)
                return null;
            sortedList = new List<Stat>();
            foreach (string player in htTotalDamagesByPlayer.Keys)
            {
                bool IsDefinatelyAnEnemy = IsDeducedEnemy(player);
                if (IsDefinatelyAnEnemy)
                {

                }
                else //else if (playersList !=null && playersList.ContainsKey(player))
                {
                    Stat newStat = new Stat(player, (long)htTotalDamagesByPlayer[player], 0);
                    //ReportingEvent revent = new ReportingEvent();
                    sortedList.Add(newStat);
                }
            }

            sortedList.Sort((StatComparer)comparer);
            return sortedList;
        }

        public bool IsDeducedEnemy(string targetPlayerOrEnemy)
        {
            if (targetPlayerOrEnemy == null || targetPlayerOrEnemy == "" || targetPlayerOrEnemy == "You")
                return false;

            bool targetContSp = targetPlayerOrEnemy.Contains(" ");
            if (targetContSp) return true;

            bool targetContDash = targetPlayerOrEnemy.Contains("-");
            if (targetContDash) return true;            

            bool isKnownEnemy = enemiesList != null && enemiesList.ContainsKey(targetPlayerOrEnemy);
            bool isKnownPlayer = playersList != null && playersList.ContainsKey(targetPlayerOrEnemy);
            if ( isKnownEnemy && !isKnownPlayer)
            {
                return true;
            }
            else
                return false;
            //if (htGroupThreatFromLog.ContainsKey(targetPlayerOrEnemy))
            //    return true;
            //else
            //    return false;
        }


        public List<ReportingEvent> GetPlayersSortedByThreatOnTarget(string targetOfHate)
        {
            if (targetOfHate == null || targetOfHate == "")
                return null;

            List<ReportingEvent> sortedList;
            ReportingEventComparer threatComparer = new ReportingEventComparer();


            if (this.htGroupThreatFromLog.Count == 0)
                return null;
            else if (!htGroupThreatFromLog.ContainsKey(targetOfHate))
                return null;

            //sortedList = new List<ReportingEvent>();

            Hashtable targetThreatTable = (Hashtable)htGroupThreatFromLog[targetOfHate];
            sortedList = GetReportingEventsFromThreatTable(targetThreatTable);

            if (sortedList!=null)
                sortedList.Sort((ReportingEventComparer)threatComparer);

            return sortedList;
        }
        public List<ReportingEvent> GetReportingEventsFromThreatTable(Hashtable targetThreatTable)
        {
            List<ReportingEvent> list = new List<ReportingEvent>();

            if (targetThreatTable == null || targetThreatTable.Count == 0)
                return null;

            foreach (string player in targetThreatTable.Keys)
            {

                if (!player.Contains(" "))/////SHOULD CHECK FOR IF NOT ENEMY LIST
                {
                    ReportingEvent revent = new ReportingEvent();

                    //Stat newStat = new Stat(player, (long)htTotalDamagesByPlayer[player], 0);
                    long playerThreatOnTarget = 0;
                    //Hashtable targetsThrTbl = (Hashtable) targetThreatTable[player];
                    playerThreatOnTarget = Convert.ToInt64(targetThreatTable[player]);
                    revent.TargetName = player;
                    revent.Amount = playerThreatOnTarget;
                    list.Add(revent);
                    //revent.Amount = (long)htGroupThreatFromLog[player];
                }
            }
            list.Sort(new ReportingEventComparer());
            return list;
        }


        private List<Stat> SortStatList(ref List<Stat> sortedList, StatComparer damageComparer)
        {
            if (this.htTotalDamagesByPlayer.Count == 0)
                return null;
            sortedList = new List<Stat>();
            foreach (string player in htTotalDamagesByPlayer.Keys)
            {
                Stat newStat = new Stat(player, (long)htTotalDamagesByPlayer[player], 0);
                sortedList.Add(newStat);
            }

            sortedList.Sort((StatComparer)damageComparer);
            return sortedList;
        }

        public List<Stat> GetPlayersSortedByHeals()
        {
            if (this.htTotalHealsByPlayer.Count == 0)
                return null;

            List<Stat> sortedList = new List<Stat>(); ;
            StatComparer comparer = new StatComparer(StatType.Healing);
            
            foreach (string player in htTotalHealsByPlayer.Keys)
            {
                if (player.Contains(" "))
                {
                }
                else{
                    Stat newStat = new Stat(player, 0, (long)htTotalHealsByPlayer[player]);
                    sortedList.Add(newStat);
                }
            }

            sortedList.Sort((StatComparer)comparer);
            return sortedList;
        }

        public long GetTotalHealing()
        {
            if (htTotalHealsByPlayer == null || htTotalHealsByPlayer.Count == 0)
                return 0;
            else
            {
                long total = 0;
                foreach (string player in htTotalHealsByPlayer.Keys)
                {
                    total += Convert.ToInt64(htTotalHealsByPlayer[player]);
                }
                return total;
            }
        }

        public long GetMaxHealingByPlayer(out string maxedPlayer)
        {
            maxedPlayer = null;
            long maxTotalByPlayer = 0;
            foreach (string player in htTotalHealsByPlayer.Keys)
            {
                if (player == null || player == "")// && !player.Contains("'"))
                { }
                else
                {
                    long totalByPlayer = Convert.ToInt64(htTotalHealsByPlayer[player]);
                    if (totalByPlayer > maxTotalByPlayer)
                    {
                        maxedPlayer = player;
                        maxTotalByPlayer = totalByPlayer;
                    }
                }
            }
            return maxTotalByPlayer;
        }

        public long GetTotalThreat(List<ReportingEvent> playersAndThreat)
        {
            if (playersAndThreat == null || playersAndThreat.Count == 0)
                return 0;
            else
            {
                long total = 0;
                foreach (ReportingEvent r in playersAndThreat)
                {
                    total += r.Amount;
                }
                return total;
            }
        }

        public long GetMaxThreatFromPlayer(out string maxedPlayer, List<ReportingEvent> playersByAmount)
        {
            maxedPlayer = null;
            if (playersByAmount == null || playersByAmount.Count == 0)
                return 0L;
 
            long maxTotalByPlayer = 0;
            foreach (ReportingEvent player in playersByAmount)
            {
                if (player.TargetName == null || player.TargetName == "")// && !player.Contains("'"))
                {
                    Debug.Assert(true);
                }
                else if (player.Amount >= maxTotalByPlayer )
                {
                        maxedPlayer = player.TargetName;
                        maxTotalByPlayer = player.Amount;
                }
            }
            return maxTotalByPlayer;
        }

        //public delegate void HandlePetDamageOrHealDelegate(ParsedLogEvent damageEvent, string petName);
        //public event HandlePetDamageOrHealDelegate PetDamage;
       // public event HandlePetDamageOrHealDelegate PetHeal;

        //public void HandlePetIsDamagingActor(ParsedLogEvent damageEvent, string petName)
        //{
        //    HandleDamage(damageEvent); //just pass along to regular damage parse event taker, for now
        
        //    //UpdateEventAmount(damageEvent, htTotalDamagesByPlayer);
        //    //UpdateThreatFromDamage(ref htGroupThreatFromLog, damageEvent);
        //    if (PetDamage!=null)
        //        PetDamage(damageEvent, petName);
        //}

        //public void HandlePetIsHealingActor(ParsedLogEvent healEvent, string petName)
        //{
        //    //UpdateEventAmount(healEvent, htTotalHealsByPlayer);

        //    //do NOT UPDATE THREAT FROM PET 
        //    //////UpdateHateFromHeal(ref htGroupThreatFromLog, healEvent);
        //    if (PetHeal!=null)
        //        PetHeal(healEvent, petName);
        //}

        public delegate void HandleLoggingEnabledDelgegate(DateTime stamp, bool enabled);
        public event HandleLoggingEnabledDelgegate LoggingEnabled;

        public void HandleLoggingStarted(DateTime stamp)
        {
            if (LoggingEnabled!=null) 
                LoggingEnabled(stamp, true);
        }

        public void HandleLoggingStopped(DateTime stamp)
        {
            if (LoggingEnabled!=null) 
                LoggingEnabled(stamp, false);
        }

        public delegate void HandleDeathDelegate(DateTime occurenceTimeStamp, string actorFullName);
        public event HandleDeathDelegate Death;

        public void HandleDeath(DateTime occurence, string actorFullName)
        {
            //remove player from every threat table
            foreach (string target in htGroupThreatFromLog.Keys)
            {
                Hashtable threatTableOfTarget = (Hashtable)htGroupThreatFromLog[target];

                if (threatTableOfTarget.ContainsKey(target))
                    threatTableOfTarget.Remove(target);
            }
            if (Death!=null)
                Death(occurence, actorFullName);
        }

        //public List<ReportingEvent> GetReportingEventsFromThreatTable()
        //{
        //    return GetReportingEventsFromThreatTable(htGroupThreatFromLog);
        //}

        public long GetMaxDamagePlayer(out string maxedPlayer, List<Stat> statsLists)
        {
            string PlayerWithMax = null;
            long maxTotalByPlayer = 0;
            foreach (Stat playerS in statsLists)
            {
                string player = playerS.Target;
                if (player == null || player == "")// && !player.Contains("'"))
                { }
                else
                {
                    long totalByPlayer = Convert.ToInt64(htTotalDamagesByPlayer[player]);
                    if (totalByPlayer > maxTotalByPlayer)
                    {
                        PlayerWithMax = player;
                        maxTotalByPlayer = totalByPlayer;
                    }
                }
            }
            maxedPlayer = PlayerWithMax;
            return maxTotalByPlayer;
        }
    } //end of class
} //end namespace as well
